﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

#region Homework Questions
/*
 * VINCENT BROWN 1/16/2009
 * 
    What is the meaning behind Class variables and Instance variables? Demostrate your answer through the creation of a class called 
        QuestionOne. Use Main() and Console.WriteLine to test your answer(s).
    -- See the code below.
  
    What is the difference between Pass By Value, and Pass By Reference?
    -- When something is passed to a function by value, changes made to the variable within the function are not maintained when the function returns.
       So if the function was called Vegas() and I pass a variable into it, whatever happens in Vegas() stays in Vegas(). In contrast, when a variable is passed by reference, 
       the changes made within the function are retained when the function returns. This is because when passing by value, a copy of the variable is 
       passed to the function whereas when passing by reference, a pointer to the original variable is used. In C#, parameters are passed by value. To
       pass by reference you would use the ref keyword. Where this can get confusing is when you pass a reference type, such as StringBuilder. So if
       you pass a StringBuilder instance into a function and set it to null within the function, when the function returns, the StringBuilder will not be
       null. However if you take that same StringBuilder instance and from within the function call the Append() method of that instance, the value
       will be appended when the function returns. This is because the the value of a reference type variable is the reference.
  
    There are 2 basics Types: user-defined and primitive (built-in). Write a Console application that highlights the differences.
    -- See the code below.
  
    What is the value in using namespaces, or what do namespaces do, in terms of functionality?
    -- Namespaces prevent the clashing of names of objects. For example, The Principal object belongs to the System.Security namespace in .NET. 
       Let's say I am developing a school payroll application and I include a Principal object. Without namespaces, the runtime would not know which
       Principal class to instantiate. Namespaces clarify the distinction between System.Security.Principal and VinsCoolApp.Principal.
  
    The Dot Operator (.) is used when you need to access two (2) things. What are those things?
    -- instance Properties and Methods
  
    For Console applications, what four (4) namespaces are automatically included during compiliation.
    -- System
       System.Collections.Generic
       System.Linq
       System.Text
 
    What is the difference between a constant and a variable?
    -- A constant remains constant while a variable is variable :P This behavior is enforced by the compiler. Under the hood, constants are metadata
       and are not stored in memory per se, while variables are kept on the stack. Constants are values which are known at compile time while 
       variables are only known at runtime. Also, constants (in C#) must be of type sbyte, byte, short, ushort, int, uint, long, ulong, char, 
       float, double, decimal, bool, string, an enum-type, or a reference-type while a variable has no such restrictions.
  
    What do these keywords mean?: const, sealed, readonly, static and final
    -- const: The const keyword is used to modify a declaration of a field or local variable. It specifies that the value of the field or the local variable cannot be modified. 
       sealed: A sealed class cannot be inherited. It is an error to use a sealed class as a base class. One uses the sealed modifier in a class declaration to prevent inheritance of the class.
       readonly: The readonly keyword is a modifier that you can use on fields. When a field declaration includes a readonly modifier, assignments to the fields introduced by the declaration can only occur as part of the declaration or in a constructor in the same class.
       static: static is used to declare a static member, which belongs to the type itself rather than to a specific object. The static modifier can be used with fields, methods, properties, operators, events and constructors, but cannot be used with indexers, destructors, or types.
       final: In java, final keyword is used to declare a const. In c#, const or readonly keyword are used to declare a constant.
  
    Show how you use preprocessor directives to include NUnit using directives into your application
    #if DEBUG
        using NUnit;
    #endif
*/
#endregion

namespace Met.CS701.CSharp.Homework 
{
    class Program
    {
        // user defined type
        public enum COLORS
        {
            Blue,
            Red,
            Majenta,
            Lilac,
            Plaid,
            Black,
            White
        }

        static void Main(string[] args)
        {
            int plaid = 4; // built-in type
            string heading = String.Format("My favorite color is {0}", Enum.GetName(typeof(COLORS), plaid));
            Console.WriteLine(heading);
            
            while (true)
            {
                string prologue = "Who would cross the Bridge of Death must answer me these questions three, ere the other side he see.";
                Console.WriteLine(prologue);

                string initialQuestion = "Are you afraid?";
                Console.WriteLine(initialQuestion);
                if (Console.ReadLine().ToLower() == "yes")
                    break;
                else
                    AskQuestions();
            }

            string done = "Pansy. Press enter to continue...";
            Console.WriteLine(done);
            Console.Read();

        }

        static bool AskQuestions()
        {
            //instance variables
            QuestionOne q1 = new QuestionOne("What is your name?", "Sir Robin of Camelot");
            QuestionOne q2 = new QuestionOne("What is your quest?", "I seek the Holy Grail.");
            QuestionOne q3 = new QuestionOne("What is the air-speed velocity of an unladen swallow?", "What do you mean? An African or European swallow?");

            q1.Ask();
            q1.AcceptAnswer(Console.ReadLine());
            if (q1.Test())
            {
                q2.Ask();
                q2.AcceptAnswer(Console.ReadLine());
                if (q2.Test())
                {
                    q3.Ask();
                    q3.AcceptAnswer(Console.ReadLine());
                    if (q3.Test())
                    {
                        Console.WriteLine("Right. Off you go.");
                        return true;
                    }
                    else
                    {
                        return Die();
                    }
                }
                else
                {
                    return Die();
                }
            }
            else
            {
                return Die();
            }
        }

        static bool Die()
        {
            for (int i = 0; i < 10; i++)
            {
                Console.WriteLine("WRONG!!! YOU DIE!!!");
            }
            return false;
        }
    }

    public class QuestionOne : BaseQuestion
    {
        public QuestionOne() : base() { }
        public QuestionOne(string q) : base(q) { }
        public QuestionOne(string q, string a) : base(q, a) { }
    }

    public interface IQuestion
    {
        void Ask();
        string AcceptAnswer(string a);
        void ShowAnswer();
    }

    public abstract class BaseQuestion: IQuestion
    {
        //Class variables (member variables)
        private string _QuestionText;
        private string _AnswerText;
        private string _UserAnswer;

        public string QuestionText
        {
            get
            {
                return this._QuestionText;
            }
            set
            {
                if (this._QuestionText != value)
                {
                    this._QuestionText = value;
                }
            }
        }
        public string AnswerText
        {
            get
            {
                return this._AnswerText;
            }
            set
            {
                if (this._AnswerText != value)
                {
                    this._AnswerText = value;
                }
            }
        }
        public string UserAnswer
        {
            get
            {
                return this._UserAnswer;
            }
            set
            {
                if (this._UserAnswer != value)
                {
                    this._UserAnswer = value;
                }
            }
        }

        public BaseQuestion()
        {
        }

        public BaseQuestion(string q)
        {
            this.QuestionText = q;
        }

        public BaseQuestion(string q, string a)
        {
            this.QuestionText = q;
            this.AnswerText = a;
        }

        public void Ask()
        {
            Console.WriteLine(this.QuestionText);
        }

        public string AcceptAnswer(string a)
        {
            this.UserAnswer = a;
            return a;
        }

        public void ShowAnswer()
        {
            Console.WriteLine(this.AnswerText);
        }

        public bool Test()
        {
            return this.AnswerText.Equals(this.UserAnswer);
        }
    }
}
